在 V8 版本9.1 中,一项重磅功能悄然推出——导入断言(import assertions)。这项功能为模块导入语句注入了一抹assert关键字的神奇力量,让其携带额外信息。一开始,这些额外信息主要用于 JavaScript 模块中导入 JSON 和 CSS 模块。
随后,导入断言经过演变,成为了导入属性。其目标依然如一:让模块导入语句携带额外信息。
最重要的变化在于,导入属性相比导入断言拥有更加灵活的语义。导入断言的语义仅限于断言,意味着附加信息不会影响模块的加载方式,只会影响是否加载。例如,JSON 模块始终根据其 MIME 类型加载为 JSON 模块,而 assert { type: 'json' }
子句只有在请求模块的 MIME 类型不是 application/json
时才导致加载失败。
然而,仅有断言的语义存在一个致命的缺陷。在网络环境中,HTTP 请求的形式取决于所请求资源的类型。比如,Accept 标头会影响响应的 MIME 类型,而 Sec-Fetch-Dest 元数据标头会影响 Web 服务器是否接受或拒绝请求。由于导入断言无法影响模块的加载方式,因此它也无法改变 HTTP 请求的形式。而请求的资源类型又会影响使用哪些内容安全策略,这让导入断言无法正确与 Web 的安全模型配合使用。
导入属性通过放宽仅有断言的语义,允许属性影响模块的加载方式。换言之,导入属性可以生成包含适当 Accept 和 Sec-Fetch-Dest 标头的 HTTP 请求。为了与新的语义匹配,旧的 assert 关键字已经被更新为
with:
// main.mjs
//
// 全新 'with' 语法。
import json from './foo.json' with { type: 'json' };
console.log(json.answer); // 42
同样,动态导入函数也已经升级,新增了 with 选项。
// main.mjs
//
// 全新 'with' 选项。
const jsonModule = await import('./foo.json', {
with: { type: 'json' }
});
console.log(jsonModule.default.answer); // 42
导入属性已在 V8 v12.3 中默认启用。
assert 关键字已在 V8 v12.3 中被弃用,并计划在 v12.6 中被彻底移除。请紧记使用 with 代替 assert!一旦使用 assert 子句,控制台将发出警告提示您改用 with。